<?php
declare(strict_types=1);

namespace Core\Service;

use App\Common\Modular\System\Serve\SmsServe;
use Core\Package\Attribute\Describe;
use JetBrains\PhpStorm\ArrayShape;
use Zms\Exception\AppException;
use Zms\ImgCaptcha\Captcha;
use function Hyperf\Config\config;
use function Hyperf\Coroutine\go;

#[Describe(title: "验证码服务")]
class VerificationCode
{

    #[Describe(title: "获取图像验证码")]
    #[ArrayShape(['sign' => "string", 'image' => "mixed|string"])]
    public function getImageVerificationCode(array $config, string $key = null): array
    {
        $key = $key ?: $this->getCodeKey();
        $result = Captcha::instance($config)->getCaptcha();
        caching()->set($key, $result['code'], 300);
        return ['sign' => $key, 'image' => $result['image'] ?? ''];
    }


    /**
     * 获取短信验证码
     * @param string $phone
     * @param string|null $key
     * @return array|bool
     * @throws AppException
     */
    #[ArrayShape(['sign' => "string", 'code' => 'string', 'debug' => 'bool'])]
    public function sendSmsVerificationCode(string $phone, string $key = null): array|bool
    {
        $key = $key ?: $this->getCodeKey();
        $_code = rand(10, 99) . rand(10, 99) . rand(10, 99);
        if (config('app.debug.VerificationCode') === true) {
            return ['sign' => $key, 'code' => $_code, 'debug' => true];
        }
        $result = container(SmsService::class)->instance()->send($phone, 'SMST-DEFAULT', ['code' => $_code]);
        if (!$result->status) {
            return false;//验证码发送失败
        }
        go(function () use ($result) {
            container(SmsServe::class)->addLog($result);
        });
        caching()->set($key, $_code, 300);
        return ['sign' => $key, 'code' => '----', 'debug' => false];
    }


    #[Describe(title: "校验验证码")]
    public function Verification(string $key, string $code): bool
    {
        if (config('app.debug.VerificationCode') === true) {
            return true;
        }
        $_code = (string)caching()->get($key) ?? '';
        return (strtoupper($_code) === strtoupper($code)) && ($_code && $code);
    }


    /**
     * 获取短信验证码标识
     * @return string
     */
    private function getCodeKey(): string
    {
        return uniqid('code.', true);
    }
}